package com.kaochong.xcx.service.impl;

import com.kaochong.xcx.cache.TokenCache;
import com.kaochong.xcx.cache.UserInfoCache;
import com.kaochong.xcx.cache.UserMistakesCache;
import com.kaochong.xcx.cache.UserWordCache;
import com.kaochong.xcx.enums.FinishStatus;
import com.kaochong.xcx.enums.ResultEnum;
import com.kaochong.xcx.enums.StageStatus;
import com.kaochong.xcx.exception.KaoChongException;
import com.kaochong.xcx.entity.UserInfo;
import com.kaochong.xcx.entity.UserMistakes;
import com.kaochong.xcx.entity.UserStageWords;
import com.kaochong.xcx.entity.WordBook;
import com.kaochong.xcx.pojo.cache.WordModel;
import com.kaochong.xcx.dao.UserInfoMapper;
import com.kaochong.xcx.dao.UserStageWordsMapper;
import com.kaochong.xcx.service.PlayGameService;
import com.kaochong.xcx.service.PrizesService;
import com.kaochong.xcx.service.UserMistakesService;
import com.kaochong.xcx.service.UserService;
import com.kaochong.xcx.service.WordBookService;
import com.kaochong.xcx.utils.DateUtil;
import com.kaochong.xcx.web.aspect.CurrentUser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;

/**
 * @author han
 * @date 2018-05-03 15:43
 */
@Service
@Slf4j
public class PlayGameServiceImpl implements PlayGameService {
	
	@Autowired
	UserInfoMapper userInfoMapper;
	
	@Autowired
	UserWordCache userWordCache;

	@Autowired
	private PrizesService prizesService;
	
	@Autowired
	UserMistakesService userMistakesService;
	
	@Autowired
	TokenCache tokenCache;
	
	@Autowired
	UserService userService;
	
	@Autowired
	UserStageWordsMapper userStageWordsMapper;
	
	@Autowired
	UserInfoCache userInfoCache;
	
	@Autowired
	UserMistakesCache userMistakesCache;
	
	@Autowired
	WordBookService wordBookService;
	
	@Override
	public Map<String, Object> begin(CurrentUser user) {
		Map<String, Object> result = new HashMap<>();
		
		List<WordModel> list = userService.todayWords(user);
		String key = userInfoCache.genKey(user.getId(), user.getTargetMarkId(), user.getCurrStage());
		Integer todayWordsSum = userInfoCache.hGetTodayWordNum(key);
		
		if (list.size() > 0) {
			// 剩余题数
			result.put("todayWordsSum", todayWordsSum);
			result.put("lastAnswerIndex", list.get(0).getRealAnswer());
			result.put("question", list.get(0));
			result.put("status", 0);
			result.put("surplus", list.size());
		} else {
			result.put("todayWordsSum", todayWordsSum);
			result.put("question", null);
			result.put("status", 1);
			result.put("surplus", 0);
		}
		return result;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, Object> answer(CurrentUser user, Integer index, Integer answerIndex) {
		Map<String, Object> result = new HashMap<>();
		
		Long userId = user.getId();
		
		// 此次培养唯一标识
		String targetMarkId = user.getTargetMarkId();
		
		Integer currStage = user.getCurrStage();
		
		WordBook wordBook = wordBookService.getWordBook(user.getTarget());
		
		Integer totalStage = wordBook.getTotalStage();
		
		// redis读取用户当前阶段的题库 TODO 需要考虑当前阶段为空的情况
		List<WordModel> list = userWordCache.get(userId, currStage, targetMarkId);
		if (index > list.size()) {
			throw new KaoChongException(ResultEnum.ANSWER_REQUEST_ERROR);
		}
		// 获取用户当前作答的题目
		WordModel wordModel = list.get(index - 1);
		// 获取正确答案
		Integer wordAnswerIndex = wordModel.getRealAnswer();
		// 判断对错
		boolean isRight = answerIndex.equals(wordAnswerIndex);
		
		// 查询错题本
		UserMistakes mistakes = userMistakesCache.hGetMistakes(userId, targetMarkId, wordModel.getId());
		
		// 对错分别处理
		if (!isRight) {
			// 答错判断错题本是否有该题
			// 没有则创建
			if (null == mistakes) {
				mistakes = new UserMistakes();
				mistakes.setUserId(userId);
				mistakes.setTargetMarkId(targetMarkId);
				mistakes.setWordId(wordModel.getId());
				mistakes.setOriginStage(currStage);
				mistakes.setStage(currStage);
				mistakes.setStatus(0);
				mistakes.setErrorTimes(1);
				mistakes.setCreateTime(new Date());
				mistakes.setUpdateTime(new Date());
				userMistakesCache.hSetMistakes(userId, targetMarkId, mistakes);
			} else{
				// 有则判断是否为当前阶段
				// 当前阶段不做错误次数累加
				// 否则累加错误次数 用作复习 且改为当前阶段
				if (!currStage.equals(mistakes.getStage())) {
					// final review复习使用
					if (mistakes.getErrorTimes() == 3) {
						mistakes.setErrorTimes(1);
					} else {
						mistakes.setErrorTimes(mistakes.getErrorTimes() + 1);
					}
					mistakes.setUpdateTime(new Date());
					mistakes.setStage(currStage);
					userMistakesCache.hSetMistakes(userId, targetMarkId, mistakes);
				}
			}
			if (currStage < totalStage) {
				// 答错 放到第八位或者是末尾
				list = restartSort(list, index);
			} else {
				list.remove(wordModel);
			}
		} else {
			// 答对判断错题本有没有此题 有则改状态为正确
			String key = userInfoCache.genKey(userId, targetMarkId, currStage);
			if (null != mistakes) {
				// 不在一个阶段 说明是final review首次答错
				if (!mistakes.getStage().equals(currStage)) {
					mistakes.setStatus(1);
					mistakes.setUpdateTime(new Date());
					//TODO 答对改为答对时的阶段
					mistakes.setStage(currStage);
					userMistakesCache.hSetMistakes(userId, targetMarkId, mistakes);
					if (currStage < totalStage) {
						userInfoCache.incRightSum(key);
					}
					// finalTest结果记录
					if (currStage >= totalStage) {
						userInfoCache.incFinalTest(key);
					}
				}
			} else {
				// 首次答对 加到已掌握单词数里
				if (currStage < totalStage) {
					userInfoCache.incRightSum(key);
				}
				// finalTest结果记录
				if (currStage >= totalStage) {
					userInfoCache.incFinalTest(key);
				}
			}
			// 答对移除此题
			list.remove(wordModel);
		}
		
		// 移除后判断是否还有题 有则返回继续答题
		if (list.size() > 0) {
			WordModel next = list.get(0);
			result.put("lastAnswerIndex", wordAnswerIndex);
			result.put("isRight", isRight);
			result.put("question", next);
			result.put("status", 0);
			result.put("surplus", list.size());
		} else {
			/**
			 * 添加抽奖资格用户
			 * addMethod by chaixuhong on 2018.07.26
			 */
			prizesService.insertFinishStagePrizeUser(userId,user.getOpenId());

			// 没有题则改变用户此阶段完成状态
			// 当前阶段状态为未完成则改变用户信息
			if (!StageStatus.FINISHED.equals(user.getCurrStageStatus())) {
				log.info("【答题】作答完毕");
				// 1、操作数据改用户当前阶段和阶段状态
				UserInfo one = userInfoMapper.selectByPrimaryKey(targetMarkId);
				
				one.setCurrStageStatus(StageStatus.FINISHED.getCode());
				Date now = new Date();
				int diffDays = DateUtil.daysBetween(one.getLastStudyTime(), now);
				if (diffDays > 1) {
					one.setKeepDay(1);
					user.setKeepDay(1);
				} else {
					int keepDay = one.getKeepDay() + 1;
					one.setKeepDay(keepDay);
					user.setKeepDay(keepDay);
				}
				one.setLastStudyTime(now);
				one.setUpdateTime(now);
				String key = userInfoCache.genKey(userId, targetMarkId, currStage);
				Integer studyNum = userInfoCache.hGetRightSum(key);
				
				if (user.getCurrStage() >= totalStage) {
					one.setFinishStatus(FinishStatus.FINISHED.getCode());
					Integer finalTest = userInfoCache.hGetFinalTest(key);
					String testResult = finalTest + "/" + userInfoCache.hGetTodayWordNum(key);
					one.setTestResult(testResult);
					user.setFinishStatus(FinishStatus.FINISHED.getCode());
				} else {
					one.setStudyWordsNum(studyNum);
				}
				userInfoMapper.updateByPrimaryKey(one);
				
				UserStageWords userStageWords = userStageWordsMapper
						.findUserStageWord(userId, targetMarkId, currStage);
				userStageWords.setFinishStatus(StageStatus.FINISHED.getCode());
				userStageWords.setUpdateTime(now);
				userStageWordsMapper.updateByPrimaryKey(userStageWords);
				
				// 2、错题加到数据库
				List<UserMistakes> mistakesAll = userMistakesCache.hGetAll(userId, targetMarkId);
				userMistakesService.save(mistakesAll, user.getTarget());
				
				// 3、更新redis用户阶段相关信息
				user.setCurrStageStatus(StageStatus.FINISHED.getCode());
				user.setLastStudyTime(now);
				user.setUpdateTime(now);
				user.setStudyWordsNum(studyNum);
				tokenCache.setToken(user.getToken(), user);
			}
			result.put("isRight", isRight);
			result.put("lastAnswerIndex", wordAnswerIndex);
			result.put("question", null);
			result.put("status", 1);
			result.put("surplus", 0);
		}
		// 将重新维护的用户此阶段问题写redis
		userWordCache.set(userId, currStage, targetMarkId, list);
		// 总题数
		String key = userInfoCache.genKey(userId, targetMarkId, currStage);
		Integer todayWordsSum = userInfoCache.hGetTodayWordNum(key);
		
		// 剩余题数
		result.put("todayWordsSum", todayWordsSum);
		return result;
	}
	
	private List<WordModel> restartSort(List<WordModel> list, Integer index) {
		index = index - 1;
		WordModel value = list.get(index);
		if (list.size() - index > 8) {
			list.remove(value);
			list.add(index + 8, value);
		} else {
			list.remove(value);
			list.add(value);
		}
		return list;
	}
	
	public static void main(String[] args) {
		Integer i1 = 1;
		Integer i2 = 2;
		Integer i3 = 3;
		Integer i4 = 4;
		Integer i5 = 5;
		Integer i6 = 6;
		Integer i7 = 7;
		Integer i8 = 8;
		Integer i9 = 9;
		Integer i10 = 10;
		
		List<Integer> idsList = new ArrayList<>();
		idsList.add(i1);
		idsList.add(i2);
		idsList.add(i3);
		idsList.add(i4);
		idsList.add(i5);
		idsList.add(i6);
		idsList.add(i7);
		idsList.add(i8);
		idsList.add(i9);
		idsList.add(i10);
		int index = 1 - 1;
		if (idsList.size() - index > 8) {
			Integer value = idsList.get(index);
			idsList.remove(value);
			idsList.add(index+8, value);
		} else {
			Integer value = idsList.get(index);
			idsList.remove(value);
			idsList.add(value);
		}
		System.out.println(idsList);
	}
}
